package com.minisoft.utils;

import cn.hutool.core.lang.Assert;
import lombok.Data;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class ReservationTimeGenerator {

    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm");

    // 中文星期到DayOfWeek的映射
    private static final Map<String, DayOfWeek> CHINESE_DAY_MAP = new HashMap<>();
    static {
        CHINESE_DAY_MAP.put("周一", DayOfWeek.MONDAY);
        CHINESE_DAY_MAP.put("周二", DayOfWeek.TUESDAY);
        CHINESE_DAY_MAP.put("周三", DayOfWeek.WEDNESDAY);
        CHINESE_DAY_MAP.put("周四", DayOfWeek.THURSDAY);
        CHINESE_DAY_MAP.put("周五", DayOfWeek.FRIDAY);
        CHINESE_DAY_MAP.put("周六", DayOfWeek.SATURDAY);
        CHINESE_DAY_MAP.put("周日", DayOfWeek.SUNDAY);
    }

    public static List<ReservationTimeSlot> generateReservationTimes(String usageTime, Duration interval, Map<String, List<String>> reservationMap) {
        List<ReservationTimeSlot> reservationTimes = new ArrayList<>();
        LocalDate today = LocalDate.now();

        // 解析开放时间字符串并生成时间表
        Map<DayOfWeek, List<AbstractMap.SimpleEntry<LocalTime, LocalTime>>> openingHours = parseOpeningHours(usageTime);

        // 生成未来7天的日期
        for (int i = 0; i < 7; i++) {
            LocalDate date = today.plusDays(i);
            DayOfWeek dayOfWeek = date.getDayOfWeek();
            if (openingHours.containsKey(dayOfWeek)) {
                for (AbstractMap.SimpleEntry<LocalTime, LocalTime> timeRange : openingHours.get(dayOfWeek)) {
                    LocalTime startTime = timeRange.getKey();
                    LocalTime endTime = timeRange.getValue();

                    // 处理当天情况，跳过已过期的时间段
                    if (date.equals(today)) {
                        LocalTime currentTime = LocalTime.now();
                        while (!startTime.isAfter(currentTime) &&
                                !startTime.plus(interval).isAfter(endTime)) {
                            startTime = startTime.plus(interval);
                        }
                        if (startTime.plus(interval).isAfter(endTime)) {
                            continue; // 跳到下一天
                        }
                    }

                    while (startTime.plus(interval).isBefore(endTime) || startTime.plus(interval).equals(endTime)) {
                        reservationTimes.add(parseReservationDate(date, startTime, startTime.plus(interval),reservationMap));
                        startTime = startTime.plus(interval);
                    }

                    // 添加剩余的时间段（如果有的话）
                    if (!startTime.equals(endTime)) {
                        reservationTimes.add(parseReservationDate(date, startTime, startTime.plus(interval),reservationMap));
                    }
                }
            }
        }
        return reservationTimes;
    }

    private static ReservationTimeSlot parseReservationDate(LocalDate date, LocalTime startTime, LocalTime endTime, Map<String, List<String>> reservationMap) {
        String dateStr = date.format(DATE_FORMATTER);
        String timeRangeStr = startTime.format(TIME_FORMATTER) + "-" + endTime.format(TIME_FORMATTER);
        List<String> reservedTimes = reservationMap.get(dateStr);
        return new ReservationTimeSlot(dateStr, timeRangeStr, reservedTimes == null || !reservedTimes.contains(timeRangeStr));
    }


    private static Map<DayOfWeek, List<AbstractMap.SimpleEntry<LocalTime, LocalTime>>> parseOpeningHours(String usageTime) {
        Map<DayOfWeek, List<AbstractMap.SimpleEntry<LocalTime, LocalTime>>> openingHours = new HashMap<>();

        // 假设输入格式为：周一至周五 08:00-18:00 或者 周六 09:00-17:00
        String[] parts = usageTime.split(" ");
        String daysPart = parts[0];
        String timesPart = parts[1];

        // 解析星期范围
        if (daysPart.contains("至")) {
            String[] dayRange = daysPart.split("至");
            DayOfWeek startDay = CHINESE_DAY_MAP.get(dayRange[0]);
            DayOfWeek endDay = CHINESE_DAY_MAP.get(dayRange[1]);

            // 计算需要遍历的天数
            int daysToIterate;
            if (startDay.getValue() <= endDay.getValue()) {
                daysToIterate = endDay.getValue() - startDay.getValue() + 1;
            } else {
                daysToIterate = 7 - startDay.getValue() + endDay.getValue() + 1;
            }

            for (int i = 0; i < daysToIterate; i++) {
                DayOfWeek day = startDay.plus(i);
                openingHours.computeIfAbsent(day, k -> new ArrayList<>()).add(parseTimeRange(timesPart));
            }
        } else {
            DayOfWeek day = CHINESE_DAY_MAP.get(daysPart);
            openingHours.computeIfAbsent(day, k -> new ArrayList<>()).add(parseTimeRange(timesPart));
        }

        return openingHours;
    }

    private static AbstractMap.SimpleEntry<LocalTime, LocalTime> parseTimeRange(String timeRange) {
        String[] times = timeRange.split("-");
        LocalTime startTime = LocalTime.parse(times[0], TIME_FORMATTER);
        LocalTime endTime = LocalTime.parse(times[1], TIME_FORMATTER);
        return new AbstractMap.SimpleEntry<>(startTime, endTime);
    }

    private static final Pattern TIME_RANGE_PATTERN = Pattern.compile(
            "^(周一|周二|周三|周四|周五|周六|周日)" +
                    "(至(周一|周二|周三|周四|周五|周六|周日))?" +
                    "\\s+((?:[01]\\d|2[0-3]):[0-5]\\d)-((?:[01]\\d|2[0-3]):[0-5]\\d)$"
    );
    public static void main(String[] args) {
        // 示例用法
        Duration interval = Duration.ofHours(2); // 时间段间隔为2小时
        String usageTime = "周一至周日 08:00-18:00"; // 开放时间
        Matcher matcher = TIME_RANGE_PATTERN.matcher(usageTime);
        Assert.isTrue(matcher.matches(), "时间格式不对");
        //已预约的时间段
        Map<String, List<String>> reservationMap = new HashMap<>();
        reservationMap.put("2024-12-06", Arrays.asList("08:00-10:00","14:00-16:00"));
        reservationMap.put("2024-12-07", Arrays.asList("10:00-12:00","12:00-14:00"));
        List<ReservationTimeSlot> times = generateReservationTimes(usageTime, interval,reservationMap);
        //按date分组转成Map，并按时间排序
        Map<String, List<ReservationTimeSlot>> result = times.stream()
                .collect(Collectors.groupingBy(ReservationTimeSlot::getDate, TreeMap::new, Collectors.toList()));
        System.out.println(JsonUtil.toJson(result));
    }

    @Data
    public static class ReservationTimeSlot {
        private String date;
        private String time;
        private boolean enable;
        public ReservationTimeSlot(String date, String time, boolean enable) {
            this.date = date;
            this.time = time;
            this.enable = enable;
        }
    }
}